/**
 * Created by Administrator on 2016/3/28.
 */

class Swiper{
    constructor(options){
        this._options=Object.assign({},this._default(),options);
        this._start = {}
        this._move = {}
        this._end = {}
        this._prev = 0
        this._current = 0
        this._offset = 0
        this._goto = -1
        this._eventHandlers = {}

        this.$box = this._options.container
        this.$container = this._options.container.querySelector('.swiper')
        this.$items = this.$container.querySelectorAll(this._options.item)
        this.count = this.$items.length

        this._width = this.$container.offsetWidth
        this._height = this._options.height === 'auto' ? this.$container.offsetHeight : this._options.height
        this.timer = null

        this._auto()
        this._init()
        this._bind()
    }
    stop(){
        clearTimeout(this.timer)
    }
    next(){
        if (this._current >= this.count - 1) {
            this._current = 0
            this._show(0)
            return this
        }
        this._prev = this._current
        this._show(++this._current)
        return this
    }
    go(index){
        if (index < 0 || index > this.count - 1 || index === this._current) {
            return
        }

        if (index === 0) {
            this._current = 0
            this._prev = 0
        } else {
            this._current = index
            this._prev = index - 1
        }

        this._goto = index
        this._show(this._current)

        return this
    }
    on(event, callback){
        if (this._eventHandlers[event]) {
            console.error('event ' + event + ' is already register')
        }
        if (typeof callback !== 'function') {
            console.error('parameter callback must be a function')
        }

        this._eventHandlers[event] = callback

        return this
    }
    destroy(){
        if (this.timer) {
            clearTimeout(this.timer)
        }
        this.$container.removeEventListener('touchstart', this.touchstartHandler, false)
        this.$container.removeEventListener('touchmove', this.touchmoveHandler, false)
        this.$container.removeEventListener('touchend', this.touchendHandler, false)
    }
    _default(){
        return {
            container: '.swiper',
            item: '.item',
            direction: 'vertical',
            activeClass: 'active',
            threshold: 50,
            duration: 300,
            auto: false,
            interval: 3000,
            height: 'auto'
        }
    }
    _auto(){
        this._options.auto&&(this.timer=setTimeout(()=>{
            this.next();
        },this._options.interval));
    }
    _init(){
        var width = this._width
        var height = this._height

        var w = width
        var h = height * this.count

        if (this._options.direction === 'horizontal') {
            w = width * this.count
            h = height
        }

        if (this._options.direction === 'vertical') {
            h = height * this.count
            this.$box.style.height = height + 'px'
        }

        this.$container.style.width = w + 'px'
        this.$container.style.height = h + 'px'

        Array.prototype.forEach.call(this.$items, function ($item, key) {
            $item.style.width = width + 'px'
            $item.style.height = height + 'px'
        })

        this._activate(0)
    }
    _bind(){
        this.touchstartHandler =(e)=>{
            this.stop()
            this._start.x = e.changedTouches[0].pageX
            this._start.y = e.changedTouches[0].pageY

            this.$container.style['-webkit-transition'] = 'none'
            this.$container.style.transition = 'none'
        }

        this.touchmoveHandler = (e)=> {
            this._move.x = e.changedTouches[0].pageX
            this._move.y = e.changedTouches[0].pageY

            var distance = this._move.y - this._start.y
            var transform = 'translate3d(0, ' + (distance - this._offset) + 'px, 0)'

            if (this._options.direction === 'horizontal') {
                distance = this._move.x - this._start.x
                transform = 'translate3d(' + (distance - this._offset) + 'px, 0, 0)'
            }

            this.$container.style['-webkit-transform'] = transform
            this.$container.style.transform = transform

            e.preventDefault()
        }

        this.touchendHandler = (e)=> {
            this._end.x = e.changedTouches[0].pageX
            this._end.y = e.changedTouches[0].pageY

            var distance = this._end.y - this._start.y
            if (this._options.direction === 'horizontal') {
                distance = this._end.x - this._start.x
            }

            this._prev = this._current
            if (distance > this._options.threshold) {
                this._current = this._current === 0 ? 0 : --this._current
            } else if (distance < -this._options.threshold) {
                this._current = this._current < (this.count - 1) ? ++this._current : this._current
            }

            this._show(this._current)
        }

        this.$container.addEventListener('touchstart', this.touchstartHandler, false)

        this.$container.addEventListener('touchmove', this.touchmoveHandler, false)

        this.$container.addEventListener('touchend', this.touchendHandler, false)

        this.$container.addEventListener('transitionEnd',(e)=>{}, false)

        this.$container.addEventListener('webkitTransitionEnd',(e)=>{
            if (e.target !== this.$container) {
                return false
            }

            if (this._current !== this._prev || this._goto > -1) {
                this._activate(this._current)
                var cb = this._eventHandlers.swiped || noop
                cb.apply(this, [this._prev, this._current])
                this._goto = -1
            }

            if (this._options.auto) {
                this._auto()
            }

            e.preventDefault()
        }, false)
    }
    _show(index){
        this._offset = index * this._height
        var transform = 'translate3d(0, -' + this._offset + 'px, 0)'

        if (this._options.direction === 'horizontal') {
            this._offset = index * this._width
            transform = 'translate3d(-' + this._offset + 'px, 0, 0)'
        }

        var duration = this._options.duration + 'ms'

        this.$container.style['-webkit-transition'] = duration
        this.$container.style.transition = duration
        this.$container.style['-webkit-transform'] = transform
        this.$container.style.transform = transform
    }
    _activate(index){
        var clazz = this._options.activeClass
        Array.prototype.forEach.call(this.$items, function ($item, key) {
            $item.classList.remove(clazz)
            if (index === key) {
                $item.classList.add(clazz)
            }
        })
    }
}

export default Swiper